﻿using System;
using System.Collections;
using System.Web.UI;
using Trentacular.SharePoint.Util;

namespace Trentacular.SharePoint.Web.UI.WebControls
{
    /// <summary>
    /// The data source view used by the <see cref="DelegateDataSource" /> control.
    /// </summary>
    public class DelegateDataSourceView : DataSourceView
    {
        /// <summary>
        /// Gets or sets the owner.
        /// </summary>
        /// <value>The owner.</value>
        public DelegateDataSource Owner { get; private set; }

        /// <summary>
        /// The default view name.
        /// </summary>
        public const string DefaultViewName = "Default_View";

        /// <summary>
        /// Initializes a new instance of the <see cref="DelegateDataSourceView"/>
        /// class.
        /// </summary>
        /// <param name="owner">The owner.</param>
        public DelegateDataSourceView(DelegateDataSource owner)
            : base(owner, DefaultViewName)
        {
            Owner = owner;
        }

        /// <summary>
        /// Gets a value indicating whether the
        /// <see cref="T:System.Web.UI.DataSourceView"/> object associated with the
        /// current <see cref="T:System.Web.UI.DataSourceControl"/> object supports the
        /// <see cref="M:System.Web.UI.DataSourceView.ExecuteDelete(System.Collections.IDictionary,System.Collections.IDictionary)"/>
        /// operation.
        /// </summary>
        /// <returns>true if the operation is supported; otherwise, false. The base
        /// class implementation returns true.
        /// </returns>
        public override bool CanDelete { get { return true; } }

        /// <summary>
        /// Gets a value indicating whether the
        /// <see cref="T:System.Web.UI.DataSourceView"/> object associated with the
        /// current <see cref="T:System.Web.UI.DataSourceControl"/> object supports the
        /// <see cref="M:System.Web.UI.DataSourceView.ExecuteInsert(System.Collections.IDictionary)"/>
        /// operation.
        /// </summary>
        /// <returns>true if the operation is supported; otherwise, false. The base
        /// class implementation returns true.
        /// </returns>
        public override bool CanInsert { get { return true; } }

        /// <summary>
        /// Gets a value indicating whether the
        /// <see cref="T:System.Web.UI.DataSourceView"/> object associated with the
        /// current <see cref="T:System.Web.UI.DataSourceControl"/> object supports the
        /// <see cref="M:System.Web.UI.DataSourceView.ExecuteUpdate(System.Collections.IDictionary,System.Collections.IDictionary,System.Collections.IDictionary)"/>
        /// operation.
        /// </summary>
        /// <value></value>
        /// <returns>true if the operation is supported; otherwise, false. The default
        /// implementation returns true.
        /// </returns>
        public override bool CanUpdate { get { return true; } }

        /// <summary>
        /// Gets a value indicating whether the
        /// <see cref="T:System.Web.UI.DataSourceView"/> object associated with the
        /// current <see cref="T:System.Web.UI.DataSourceControl"/> object supports
        /// paging through the data retrieved by the
        /// <see cref="M:System.Web.UI.DataSourceView.ExecuteSelect(System.Web.UI.DataSourceSelectArguments)"/>
        /// method.
        /// </summary>
        /// <value></value>
        /// <returns>true if the operation is supported; otherwise, false. The base
        /// class implementation returns false.
        /// </returns>
        public override bool CanPage { get { return Owner.CanPage; } }

        /// <summary>
        /// Gets a value indicating whether the
        /// <see cref="T:System.Web.UI.DataSourceView"/> object associated with the
        /// current <see cref="T:System.Web.UI.DataSourceControl"/> object supports
        /// retrieving the total number of data rows, instead of the data.
        /// </summary>
        /// <value></value>
        /// <returns>true if the operation is supported; otherwise, false. The base
        /// class implementation returns false.
        /// </returns>
        public override bool CanRetrieveTotalRowCount
        {
            get { return Owner.CanRetrieveTotalRowCount; }
        }

        /// <summary>
        /// Gets a value indicating whether the
        /// <see cref="T:System.Web.UI.DataSourceView"/> object associated with the
        /// current <see cref="T:System.Web.UI.DataSourceControl"/> object supports a
        /// sorted view on the underlying data source.
        /// </summary>
        /// <value></value>
        /// <returns>true if the operation is supported; otherwise, false. The default
        /// implementation returns false.
        /// </returns>
        public override bool CanSort { get { return Owner.CanSort; } }

        /// <summary>
        /// Sorts the specified results.
        /// </summary>
        /// <param name="results">The results.</param>
        /// <param name="sortExpression">The sort expression.</param>
        /// <returns></returns>
        protected virtual IEnumerable Sort(IEnumerable results, string sortExpression)
        {
            var sortArgs = sortExpression.Split(' ');
            if (sortArgs.Length == 0)
                return results;

            var sortProperty = sortArgs[0];
            if (sortProperty.Length == 0)
                return results;

            var reverse = false;
            if (sortArgs.Length > 1 && sortArgs[1].Equals("desc", StringComparison.CurrentCultureIgnoreCase))
                reverse = true;

            return results.Sort(reverse, sortProperty);
        }

        /// <summary>
        /// Gets a list of data from the underlying data storage.
        /// </summary>
        /// <param name="arguments">A
        /// <see cref="T:System.Web.UI.DataSourceSelectArguments"/> that is used to
        /// request operations on the data beyond basic data retrieval.</param>
        /// <returns>
        /// An <see cref="T:System.Collections.IEnumerable"/> list of data from the
        /// underlying data storage.
        /// </returns>
        protected override IEnumerable ExecuteSelect(
            DataSourceSelectArguments arguments
            )
        {
            var results = Owner.OnSelect(arguments);

            // Sort the results if AutoSort is specified
            if (Owner.AutoSort)
                return Sort(results, arguments.SortExpression);

            return results;
        }

        /// <summary>
        /// Performs an insert operation on the list of data that the
        /// <see cref="T:System.Web.UI.DataSourceView"/> object represents.
        /// </summary>
        /// <param name="values">An <see cref="T:System.Collections.IDictionary"/> of
        /// name/value pairs used during an insert operation.</param>
        /// <returns>
        /// The number of items that were inserted into the underlying data storage.
        /// </returns>
        /// <exception cref="T:System.NotSupportedException">
        /// The
        /// <see cref="M:System.Web.UI.DataSourceView.ExecuteInsert(System.Collections.IDictionary)"/>
        /// operation is not supported by the
        /// <see cref="T:System.Web.UI.DataSourceView"/>.
        /// </exception>
        protected override int ExecuteInsert(IDictionary values)
        {
            return Owner.OnInsert(values);
        }

        /// <summary>
        /// Performs an update operation on the list of data that the
        /// <see cref="T:System.Web.UI.DataSourceView"/> object represents.
        /// </summary>
        /// <param name="keys">An <see cref="T:System.Collections.IDictionary"/> of
        /// object or row keys to be updated by the update operation.</param>
        /// <param name="values">An <see cref="T:System.Collections.IDictionary"/> of
        /// name/value pairs that represent data elements and their new values.
        /// </param>
        /// <param name="oldValues">An <see cref="T:System.Collections.IDictionary"/>
        /// of name/value pairs that represent data elements and their original values.
        /// </param>
        /// <returns>
        /// The number of items that were updated in the underlying data storage.
        /// </returns>
        /// <exception cref="T:System.NotSupportedException">
        /// The
        /// <see cref="M:System.Web.UI.DataSourceView.ExecuteUpdate(System.Collections.IDictionary,System.Collections.IDictionary,System.Collections.IDictionary)"/>
        /// operation is not supported by the
        /// <see cref="T:System.Web.UI.DataSourceView"/>.
        /// </exception>
        protected override int ExecuteUpdate(
            IDictionary keys,
            IDictionary values,
            IDictionary oldValues
            )
        {
            return Owner.OnUpdate(keys, values, oldValues);
        }

        /// <summary>
        /// Performs a delete operation on the list of data that the
        /// <see cref="T:System.Web.UI.DataSourceView"/> object represents.
        /// </summary>
        /// <param name="keys">An <see cref="T:System.Collections.IDictionary"/> of
        /// object or row keys to be deleted by the
        /// <see cref="M:System.Web.UI.DataSourceView.ExecuteDelete(System.Collections.IDictionary,System.Collections.IDictionary)"/>
        /// operation.</param>
        /// <param name="oldValues">An <see cref="T:System.Collections.IDictionary"/>
        /// of name/value pairs that represent data elements and their original values.
        /// </param>
        /// <returns>
        /// The number of items that were deleted from the underlying data storage.
        /// </returns>
        /// <exception cref="T:System.NotSupportedException">
        /// The
        /// <see cref="M:System.Web.UI.DataSourceView.ExecuteDelete(System.Collections.IDictionary,System.Collections.IDictionary)"/>
        /// operation is not supported by the
        /// <see cref="T:System.Web.UI.DataSourceView"/>.
        /// </exception>
        protected override int ExecuteDelete(IDictionary keys, IDictionary oldValues)
        {
            return Owner.OnDelete(keys, oldValues);
        }
    }
}
